MacLock
Volume Number: 7
Issue Number: 7
Column Tag: MacOOPs!
MacLock
By Mark Bykerk-Kauffman, Chico, CA
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
MacLock 1.0: A Complete Object-Oriented Application
[Since the publication of his article, “Intro to OOP,” in the Sept. 1990 issue of
MacTutor, Mark Kauffman has left his design/programming job with Burr Brown in
Tucson, and moved to Chico, CA. In Chico, Mark is working toward a Bachelors Degree
in Computer Science with an emphasis on systems programming. He has owned and
programmed a Macintosh since it’s introduction in 1984.]
Origins
While working on a UNIX development system I came across a program called
XLOCK. It displayed an icon of an open lock on the screen. When you pressed the lock
button on the lock, the lock closed and the system was cut off from further input by the
keyboard or mouse. To unlock the system you typed in a password and pressed the
Return key. It was possible to change the password by calling up a password dialog. I
hadn’t seen a similar program on the Macintosh and I wondered if it would be possible to
write a lock program that ran under MultiFinder. Since UNIX is multi-user I knew that
somehow the program was taking all input away from the operating system once the
lock button was pressed. Could I write a routine with THINK C that took away all input
away from MultiFinder while waiting for a password? Could I build an application that
looked and acted like XLOCK? I decided that if someone could do it on UNIX system, I
could do it on the Mac. This article describes the complete MacLock application that
I’ve been distributing as One-Dollar Shareware.
One-Dollar Shareware
When I first started working with microcomputers there was a spirit of
generosity among the hobbyists who owned and programmed them. Most games and
small applications cost under $50. We still see some of that generosity in the large
number of shareware programs available. HyperCard is another example of
programmers generosity. In an attempt to keep that spirit alive, I came up with the
idea of One-Dollar Shareware. The source code is yours to use; but please, let me
continue to distribute the compiled program as shareware. And if you come up with a
nifty program, consider distributing it as One-Dollar Shareware. I’ll be glad to send
you my dollar.
Dodging The Lawyers
MacLock was written using the class library in THINK C 4.0 and the Resource
Editor. Prior to writing this article, I wrote the program following the instructions in
the THINK C User’s Manuel in the chapter “The THINK Class Library” under the
section “Writing an Application with the THINK Class Library.” When I started to
write this article I realized that three of the classes I had defined, CMacLockApp,
CMacLockDoc, and CMacLockPane contained large portions of source code from
Symantec’s “Starter” demonstration. Rather than worry about copyright laws and
whether I was violating Symantec’s License Agreement which states, “You may not in
any event distribute any of the source files provided or licensed as part of the
software,” I decided to rewrite my source code so that the classes I defined contained
only the code necessary for them to function.
Sounds like a lot of work doesn’t it? It wasn’t. What I did to solve the problem
illustrates the beauty of one of the features of object-oriented programming,
inheritance. Instead of having CMacLockApp, CMacLockDoc and CMacLockPane (the C
prefix indicates a class structure) be direct descendants of CApplication, CDocument
and CPane I made them subclasses of CStarterApp, CStarterDoc and CStarterPane in the
“Starter” demonstration folder. Writing an application this way follows one of the
basic rules of object oriented programming. Build new objects that are based on
similar objects then write just the few methods and instance variables necessary to
make your application unique. Programming this way means that it’s not necessary for
CMacLockApp to contain an Exit method or a SetUpFileParameters method, because
MacLock doesn’t act any differently than the Starter demonstration when responding to
an Exit or a SetUpFileParameters message. Nor do CMacLockDoc and CMacLockPane
need to contain any method whose function has already been defined in the Starter
demonstration and is not unique to the MacLock application.
Before I give step by step instructions on how to build the MacLock application,
I’d like to discuss some other basic ideas that gave me guidance designing an
object-oriented program.
Thinking OOP
Another rule of object-oriented programming is that you must think in terms of
objects. In his book, Object-oriented Software Construction, Dr. Bertrand Meyer says
in the preface that object-oriented design means that you base your software on objects
NOT on the actions your computing system takes on those objects. Why think
object-oriented? Dr. Meyer spends the first three chapters of his book explaining why
large function-oriented programs have problems with correctness, robustness,
extendibility, reusability and compatibility. In the fourth chapter he defines an object
and how using objects to design software solves those problems. Since there’s not
enough space here to write a book, what follows are just a few guidelines I found useful
while writing an object-oriented program.
First, replace global variables with global objects. Let me give an example.
There is a file, “Commands.h”, that Symantec uses to define all the commands to which
a common Macintosh application responds. The object-oriented way of implementing
Commands would have been to define a class CCommands(based on an existing class if
possible) then creating an object, gCommands, at run time with the statement
gCommands=new(CCommands). What would our software do with the object
gCommands? We could send it messages like cmdOpen, cmdSave, cmdNew and expect a
number back. And we would need to destroy it when we are done using it.
You might ask, “Why would I go to the trouble of creating an object to implement
something as simple as a global list of commands and their corresponding values?”
Another reason object-oriented programming works better than function-oriented
programming is it’s extendibility. What if tomorrow some new part Symantec’s
system required that Commands.h did more than return an integer for each command,
like wait until several commands were sent before responding? What if they needed
the integer returned to depend on the order of commands recieved? It would be easy to
extend a class CCommands to include these functions without affecting the rest of the
software. Of course the likelihood of Commands.h needing to do these other things is
small, so in THINK C the quickest and easiest way to implement what was necessary is
to create an include file of simple global constants. But some of the new purely
object-oriented languages like Eiffel require that anything global to a software system
be an object. And if purely object-oriented design fulfills Dr. Meyer’s promise of
drastically reducing s eventy percent of the software costs associated with maintenance,
we had better start to work that way.
When I designed MacLock, the above idea was reinforced by what happened to me
when I started implementing the password. I tried to have the password be a global
variable. There were problems; the password kept disappearing. The system would not
work correctly until I created a password object.
Second, use what’s already there. Symantec gave us a lot more than menus,
windows and buttons with their Class Library. We have CCollection, CList, CChore,
CEditText, CPane and more. You will find that most of what you want your application to
do is already defined by these classes and that all you need to do is create classes that
inherit properties from these then add or modify a method here and there.
Writing your program this way will save you a lot of time. Initially you will
spend time learning the THINK C class library, but that only happens ONCE.
Third, if you use a resource, you should create an object. I discovered this rule
while working on routines to read in the password from the keyboard and open the lock.
Placing the dialog box and everything else concerning the password into an object made
the program a lot easier to work with. Another place I should use an object, but
haven’t, is for the lock icon that opens and closes. It’s still easier for me to see objects
after I’m done writing a program. I’ve left the code the way it is so that you can see the
difference between object-oriented programming (CPassword) and function-oriented
programming (the lock icon).
The following paragraphs describe how to set up the MacLock project. It is a bit
different than a standard project, so please follow the instructions carefully. You
should do things in the order given and test the application after each section.
Arrange the Folders Used by MacLock
Because the MacLock Application, Document and Pane classes are inherited from
the Starter demonstration you will need to move the folder “TCL Demos” into the folder
“Think C”. When the THINK C compiler looks for #include files it looks in your